package controller

import (
	"fmt"

	. "gddgame.cc/galaxy/common/dsl/web"
	"gddgame.cc/galaxy/project/breeder/breeder/model"
	"gddgame.cc/galaxy/utils"
	"gddgame.cc/galaxy/utils/def"
	"gddgame.cc/galaxy/utils/orm"
)

func CreateMap(context def.Context, userId int, name string, content string, people int, aiNumber int, data []byte) (*model.Map, error) {
	mapItem := model.Map{
		Id:       0,
		UserId:   userId,
		Name:     name,
		Content:  content,
		People:   people,
		No:       0,
		AiNumber: aiNumber,
		Version:  0,
		Data:     data,
		Review:   false,
	}
	if _, err := MapModel.Insert(&mapItem); err != nil {
		return nil, SystemExceptionDetail("添加失败", err)
	}
	return &mapItem, nil
}

func StartMap(context def.Context, ns string, mapNoId string) (*model.MapNo, error) {
	var mapNo model.MapNo
	aiField := "ai_node"
	if ns == "local" {
		aiField += "_local"
	}
	if ok, _ := MapNoModel.PK(mapNoId).One(&mapNo); !ok {
		return nil, ValidException("地图实例不存在")
	}
	if mapNo.Status {
		return &mapNo, ValidException("地图已经启动")
	}

	if _, err := MapNoModel.PK(mapNoId).Update(map[string]interface{}{
		"status": 1,
		// 设置ai可启动
		aiField: nil,
	}); err != nil {
		return nil, SystemExceptionDetail("更新失败", err)
	}
	return &mapNo, nil
}

func StopMap(context def.Context, ns string, mapNoId string) (*model.MapNo, error) {
	var mapNo model.MapNo
	aiField := "ai_node"
	if ns == "local" {
		aiField += "_local"
	}
	if ok, _ := MapNoModel.PK(mapNoId).One(&mapNo); !ok {
		return nil, ValidException("地图实例不存在")
	}
	if !mapNo.Status {
		return &mapNo, ValidException("地图还未启动")
	}

	if _, err := MapNoModel.PK(mapNoId).Update(map[string]interface{}{
		"status": 0,
		// 清空ai
		aiField: nil,
	}); err != nil {
		return nil, SystemExceptionDetail("更新失败", err)
	}
	return &mapNo, nil
}

func GetMap(context def.Context, mapId int) (*model.Map, error) {
	var mapItem model.Map
	if ok, _ := MapModel.PK(mapId).One(&mapItem); !ok {
		return nil, ValidException("地图不存在")
	}
	return &mapItem, nil
}

func ListMap(context def.Context, mapIds []int) ([]model.Map, error) {
	var list []model.Map
	if _, err := MapModel.Query().Where("in", "id", mapIds).Find(&list); err != nil {
		return nil, ValidException("地图不存在")
	}
	return list, nil
}

func GetMapNo(context def.Context, mapNoId string) (*model.Map, *model.MapNo, error) {
	var mapNo model.MapNo
	if ok, _ := MapNoModel.PK(mapNoId).One(&mapNo); !ok {
		return nil, nil, ValidException("地图实例不存在")
	}

	var mapItem model.Map
	if ok, _ := MapModel.PK(mapNo.MapId).One(&mapItem); !ok {
		return nil, nil, ValidException("地图不存在")
	}
	return &mapItem, &mapNo, nil
}

func ListMapNo(context def.Context, status bool) ([]model.MapNo, error) {
	var list []model.MapNo
	if _, err := MapNoModel.Query().Where("=", "status", status).Find(&list); err != nil {
		return nil, ValidException("地图实例不存在")
	}
	return list, nil
}

func ListMapNoWithAuth(context def.Context) ([]model.MapNo, error) {
	var list []model.MapNo
	if _, err := MapNoModel.Query().Where("=", "auto_start", true).Find(&list); err != nil {
		return nil, ValidException("地图实例不存在")
	}
	return list, nil
}

func UpdateMap(context def.Context, userId int, mapId int, people int, aiNumber int, data []byte) (int, error) {
	var mapItem model.Map
	if ok, err := MapModel.PK(mapId).One(&mapItem); !ok {
		return 0, err
	}
	//if mapItem.UserId != userId {
	//	return ValidException("没有管理权限")
	//}
	item := map[string]interface{}{}
	if people > 0 {
		item["people"] = people
	}
	if aiNumber > 0 {
		item["ai_number"] = aiNumber
	}
	if data != nil {
		item["data"] = data
		item["version"] = &orm.UpdateOperate{
			Operate: "+",
			Value:   1,
		}
	}

	if _, err := MapModel.PK(mapId).Update(item); err != nil {
		return 0, SystemExceptionDetail("更新失败", err)
	}
	return mapItem.Version + 1, nil
}

func CreateNo(context def.Context, mapItem *model.Map) (*model.MapNo, error) {
	if _, err := MapModel.PK(mapItem.Id).Update(map[string]interface{}{
		"no": &orm.UpdateOperate{
			Operate: "+",
			Value:   1,
		},
	}); err != nil {
		return nil, SystemExceptionDetail("更新失败", err)
	}
	mapNoId := mapItem.EncodeNo(mapItem.No + 1)
	mapNo := model.MapNo{
		Id:     mapNoId,
		MapId:  mapItem.Id,
		People: 0,
	}
	if _, err := MapNoModel.Insert(&mapNo); err != nil {
		return nil, SystemExceptionDetail("添加失败", err)
	}
	return &mapNo, nil
}

func JoinNo(context def.Context, mapNoId string, userId int, isSystem bool) (*model.UserMap, bool, error) {
	var mapNo model.MapNo
	if ok, _ := MapNoModel.PK(mapNoId).One(&mapNo); !ok {
		return nil, false, ValidException("地图实例不存在")
	}
	var mapItem model.Map
	if ok, _ := MapModel.PK(mapNo.MapId).One(&mapItem); !ok {
		return nil, false, ValidException("地图不存在")
	}
	var userMap model.UserMap
	if ok, _ := UserMapModel.Query().Where("=", "map_no", mapNoId).Where("=", "user_id", userId).One(&userMap); !ok {
		// 判断已经有个人数
		if isSystem {
			c, _ := UserMapModel.Query().Where("=", "map_no", mapNoId).Where("=", "is_system", 1).Count()
			if int(c) >= mapItem.AiNumber {
				return nil, false, ValidException("ai数量已满")
			}
		}
		i, _ := MapNoModel.PK(mapNo.Id).Update(map[string]interface{}{
			"people": &orm.UpdateOperate{
				Operate: "+",
				Value:   1,
			},
		})
		if i == 0 {
			return nil, false, ValidException("加入失败")
		}
		userMap = model.UserMap{
			UserId: userId,
			MapId:  mapNo.MapId,
			MapNo:  mapNoId,
		}
		if _, err := UserMapModel.Insert(&userMap); err != nil {
			return nil, false, SystemExceptionDetail("添加任务失败", err)
		}

		return &userMap, true, nil
	}
	return &userMap, false, nil
}

func ReleaseAi(context def.Context, userId int) error {
	var user model.User
	if err := Center.GetUser(userId, &user); err != nil {
		return SystemExceptionDetail("更新失败", err)
	}
	if err := Center.UpdateUser(&user, map[string]interface{}{
		"status": 0,
	}); err != nil {
		return SystemExceptionDetail("更新失败", err)
	}
	return nil
}

func FindFreeAi(content def.Context) (*model.User, error) {
	var user model.User
	if err := Center.RandomUser(&user, []string{"`is_system`=1", "`status`=0"}); err != nil {
		return nil, err
	}
	return &user, nil
}

func FindFreeMap(context def.Context, ns string, id string, node string) (*model.MapNo, error) {
	var item model.MapNo
	aiField := "ai_node"
	if ns == "local" {
		aiField += "_local"
	}
	if n, err := MapNoModel.Query().Where("=", "status", true).WhereSql("(" + aiField + " is null or " + aiField + " = '')").One(&item); err != nil {
		fmt.Println(err)
		return nil, ValidException("地图实例不存在")
	} else if !n {
		return nil, nil
	}
	if n, err := MapNoModel.PK(item.Id).WhereSql("(" + aiField + " is null or " + aiField + " = '')").Update(map[string]interface{}{
		aiField: node + "/" + id,
	}); err != nil {
		return nil, ValidException("更新地图失败")
	} else if n == 0 {
		// 乐观锁，再次申请
		return FindFreeMap(context, ns, id, node)
	}
	return &item, nil
}

func TransferMap(context def.Context, ns string, id string, node string, number int) (*model.MapNo, error) {
	// 找一个比当前节点占领数量多的释放
	var item model.MapNo
	aiField := "ai_node"
	if ns == "local" {
		aiField += "_local"
	}
	c, err := MapNoModel.Query().Where("=", "status", true).FieldAlias("count(DISTINCT("+aiField+")) ", "ai_number").FieldAlias("count(id)", "number").OneString()
	if err != nil {
		fmt.Println(err)
		return nil, nil
	}
	aiNumber := utils.ToInt(c["ai_number"])
	if number == 0 {
		aiNumber += 1
	}
	total := utils.ToInt(c["number"])
	if total == 0 {
		return nil, nil
	}
	fmt.Println("transfer", aiNumber, total, number)
	if number >= aiNumber/total {
		return nil, nil
	}
	if ok, err := MapNoModel.Query().Where("=", "status", true).WhereSql(aiField+" != ? or ("+aiField+" is null or "+aiField+" = '') group by "+aiField+" having count(id) - 1 > ? ", node+"/"+id, number).FieldAlias("max(id)", "id").FieldAlias(aiField, "ai_node").One(&item); err != nil {
		fmt.Println(err)
		return nil, nil
	} else if !ok {
		return nil, nil
	}
	fmt.Println("transfer", item)
	if n, err := MapNoModel.PK(item.Id).Where("=", aiField, item.AiNode).Update(map[string]interface{}{
		aiField: node + "/" + id,
	}); err != nil {
		fmt.Println(err)
		return nil, ValidException("更新地图失败")
	} else if n == 0 {
		// 乐观锁，再次申请
		return TransferMap(context, ns, id, node, number)
	}
	return &item, nil
}

func ReleaseMap(context def.Context, ns string, mapNoId string, id string, node string) error {
	var mapNo model.MapNo
	aiField := "ai_node"
	if ns == "local" {
		aiField += "_local"
	}
	if ok, _ := MapNoModel.PK(mapNoId).FieldAlias(aiField, "ai_node").One(&mapNo); !ok {
		return ValidException("地图实例不存在")
	}
	if mapNo.AiNode != node+"/"+id {
		return ValidException("地图实例非当前管理对象")
	}
	if _, err := MapNoModel.PK(mapNoId).Update(map[string]interface{}{
		aiField: nil,
	}); err != nil {
		return ValidException("地图实例更新失败")
	}
	return nil
}

func UpdateNode(content def.Context, mapId int, version int, nodeList []model.MapNode) error {
	var mapItem model.Map
	if ok, _ := MapModel.PK(mapId).One(&mapItem); !ok {
		return ValidException("地图不存在")
	}
	var mapNodeList []model.MapNode
	if _, err := MapNodeModel.Query().Where("=", "map_id", mapItem.Id).Find(&mapNodeList); err != nil {
		return ValidException("地图不存在")
	}
	mapNodeMap := make(map[int]map[int]model.MapNode)

	nodeMap := make(map[int]map[int]struct{})
	for _, mapNode := range mapNodeList {

		if _, ok := mapNodeMap[mapNode.X]; !ok {
			mapNodeMap[mapNode.X] = make(map[int]model.MapNode)
		}
		m := mapNodeMap[mapNode.X]
		if _, ok := m[mapNode.Y]; !ok {
			m[mapNode.Y] = mapNode
		}
	}
	for _, node := range nodeList {
		if _, ok := nodeMap[node.X]; !ok {
			nodeMap[node.Y] = make(map[int]struct{})
		}
		m := nodeMap[node.X]
		if _, ok := m[node.Y]; !ok {
			m[node.Y] = struct{}{}
		}
	}
	newNode := []map[string]interface{}{}
	oldNode := []int{}
	updateNode := []int{}
	for _, node := range nodeList {
		if m, ok := mapNodeMap[node.X]; !ok {
			goto New
		} else if v, ok := m[node.Y]; !ok {
			goto New
		} else {
			if !v.Status {
				updateNode = append(updateNode, v.Id)
			}
		}
		continue
	New:
		newNode = append(newNode, map[string]interface{}{
			"name":      node.Name,
			"map_id":    mapItem.Id,
			"x":         node.X,
			"y":         node.Y,
			"data_type": node.DataType,
			"mode":      node.Mode,
			"version":   version,
			"status":    1,
		})
	}
	for _, node := range mapNodeList {
		if m, ok := nodeMap[node.X]; !ok {
			goto Old
		} else if _, ok := m[node.Y]; !ok {
			goto Old
		}
		continue
	Old:
		oldNode = append(oldNode, node.Id)
	}
	if len(newNode) > 0 {
		if _, err := MapNodeModel.Query().Insert(newNode...); err != nil {
			return SystemExceptionDetail("添加节点失败", err)
		}
	}
	if len(oldNode) > 0 {
		if _, err := MapNodeModel.Query().Where("in", "id", oldNode).Update(map[string]interface{}{
			"status":  0,
			"version": version,
		}); err != nil {
			return SystemExceptionDetail("更新失败", err)
		}
	}

	if len(updateNode) > 0 {
		if _, err := MapNodeModel.Query().Where("in", "id", updateNode).Update(map[string]interface{}{
			"status": 1,
		}); err != nil {
			return SystemExceptionDetail("更新失败", err)
		}
	}
	return nil
}

func GetNodes(content def.Context, mapId int) ([]model.MapNode, error) {
	var mapNodeList []model.MapNode
	if _, err := MapNodeModel.Query().Where("=", "map_id", mapId).Find(&mapNodeList); err != nil {
		return nil, ValidException("地图节点不存在")
	}
	return mapNodeList, nil
}
